package com.wanglianyun.controller;

import com.alibaba.fastjson.JSON;
import com.wanglianyun.redis.RedisUtil;
import com.wanglianyun.request.PublishRequest;
import com.wanglianyun.service.RedissonClientApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;

@RestController
@RequestMapping("/test")
public class HelloController {

    private static final String RANK_KEY = "subject_rank";

    private static final String SUBJECT_LIKED_KEY = "subject.liked";

    private static final String SUBJECT_LIKED_COUNT_KEY = "subject.liked.count";

    private static final String SUBJECT_LIKED_DETAIL_KEY = "subject.liked.detail";

    private static final String LOCK_KEY = "stock_lock:";

    @Resource
    private RedisUtil redisUtil;

    @Autowired
    RedissonClientApi redissonClientApi;

    /**
     *
     * @param key 姓名
     * @param subjectId 题目id
     * @param status 是否喜欢，1喜欢 0不喜欢
     * @return 返回
     */
    @GetMapping("/hello")
    public String hello(@RequestParam String key, @RequestParam int status, @RequestParam String subjectId) {
        System.out.println("hello world");

        // redis放入zadd计入排行榜，每一个member都关联一个score
        redisUtil.addScore(RANK_KEY, key, 1);

        // 记录点赞的人
        String hashKey = buildSubjectLikedKey(subjectId, key);
        //1代表喜欢，0代表不喜欢
        redisUtil.putHash(SUBJECT_LIKED_KEY, hashKey, 1);

        // 用户是否点赞题目
        String detailKey = SUBJECT_LIKED_DETAIL_KEY + "." + subjectId + "." + key;
        // 题目点赞数量
        String countKey = SUBJECT_LIKED_COUNT_KEY + "." + subjectId;
        if (1 == status) {
            redisUtil.increment(countKey, 1);
            redisUtil.set(detailKey, "1");
        } else {
            Integer count = redisUtil.getInt(countKey);
            if (!Objects.isNull(count) && count > 0) {
                redisUtil.increment(countKey, -1);
                redisUtil.del(detailKey);
            }
        }
        //计算题目点赞数量
        String countKeyNum = SUBJECT_LIKED_COUNT_KEY + "." + subjectId;
        Integer count = redisUtil.getInt(countKeyNum);
        System.out.println("题目" + subjectId + "点赞数量为：" + count);

        //题目贡献榜
        Set<ZSetOperations.TypedTuple<String>> typedTuples = redisUtil.rankWithScore(RANK_KEY, 0, 5);
        typedTuples.forEach((rank -> {
            System.out.println(rank.getValue() + "贡献题目数量为：" + rank.getScore().intValue());
        }));

        System.out.println("开始publish消息给redis订阅者");
        // 方式一发送map
        Map<String, String> map = new HashMap<>();
        map.put(key, subjectId);
        redisUtil.publish("__bili_like__", JSON.toJSONString(map));
        // 方式二发送对象
//        PublishRequest publishRequest = new PublishRequest(key, subjectId);
//        redisUtil.publish("__bili_like__", JSON.toJSONString(publishRequest));
        return "hello world";
    }

    @GetMapping("/order")
    public String lock(@RequestParam String productId) {
        String lockKey = LOCK_KEY + productId;
        String requestId = UUID.randomUUID().toString();
        try {
            boolean isLockAcquire = redisUtil.tryGetDistributedLock(lockKey, requestId, 10);
            if (!isLockAcquire) {
                System.out.println("上锁失败");
                throw new RuntimeException("Failed to acquire distribute lock for product: " + productId);
            }
            //上锁成功，执行库存扣减操作
            System.out.println("获取到锁开始执行库存扣减业务操作");

        } finally {
            //释放分布式锁
            redisUtil.releaseDistributedLock(lockKey, requestId);
        }
        return "lock";
    }

    @GetMapping("/redisson")
    public String redissonLock(@RequestParam String productId) {
        redissonClientApi.deductStockWithRedisson(productId);
        return "redisson-lock";
    }

    private String buildSubjectLikedKey(String subjectId, String userId) {
        return subjectId + ":" + userId;
    }
}